package com.xiaoyi.util;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;

import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * @author 小易
 * @version 1.0
 * @description TODO JWT生成与验证的工具类
 * @date 2022/12/5 17:39
 */
public class JwtUtils {

    public static final String JWT_SECRET = "8677df7fc3a34e26a61c034d5ec8245d"; //密匙
    public static final long EXPIRE_TIME = 24 * 60 * 60 * 1000; //token有效时间

    /**
     * @description 外部使用：创建加密token
     * @param id claimsId
     * @param map 存储的数据
     * @return java.lang.String
     * @author 小易
     * @date 2022/12/6 9:53
     */
    public static String createToken(String id, Map<String, Object> map){
        return createToken(id, null, map, generalKey(JWT_SECRET), EXPIRE_TIME);
    }

    /**
     * @description 外部使用：创建加密token
     * @param map 存储的数据
     * @return java.lang.String
     * @author 小易
     * @date 2022/12/6 9:53
     */
    public static String createToken(Map<String, Object> map){
        return createToken(null, null, map, generalKey(JWT_SECRET), EXPIRE_TIME);
    }

    /**
     * @description 创建加密token
     * @param id claimsId，如果设置了，在解析时也要传入
     * @param subject 说明
     * @param map 存储的数据
     * @param ttlMillis token过期时间
     *@return java.lang.String
     * @author 小易
     * @date 2022/12/6 8:53
     */
    private static String createToken(String id, String subject, Map<String, Object> map,  byte[] secretKey, long ttlMillis) {
        if (map == null) {
            map = new HashMap<>(0);
        }
        Claims claims = Jwts.claims(map).setSubject(subject).setId(id).setExpiration(new Date(System.currentTimeMillis() + ttlMillis));
        JwtBuilder jwtBuilder = Jwts.builder().setClaims(claims)
                .signWith(Keys.hmacShaKeyFor(secretKey), SignatureAlgorithm.HS512);
        return jwtBuilder.compact();
    }

    /**
     * @description 生成加密key
     * @param secretKey 密钥
     *@return byte[]
     * @author 小易
     * @date 2022/12/6 10:12
     */
    private static byte[] generalKey(String secretKey) {
        if (secretKey.length() < 64) {
            //如果key的长度不够，在前面补空格
            secretKey = String.format("%64s", secretKey);
        }
        byte[] bytes = new byte[0];
        try {
            bytes = secretKey.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return bytes;
    }

    /**
     * @description 解密token
     * @param id claimsId
     * @param token token
     * @return io.jsonwebtoken.Claims
     * @author 小易
     * @date 2022/12/6 10:24
     */
    public static Claims parseToken(String id, String token) {
        JwtParserBuilder builder = Jwts.parserBuilder();
        if (id != null) {
            builder.requireId(id);
        }
        Jws<Claims> claimsJws = builder
                .setSigningKey(generalKey(JWT_SECRET))
                .build()
                .parseClaimsJws(token);
        return claimsJws.getBody();
    }

    /**
     * @description 解密token
     * @param token token
     * @return io.jsonwebtoken.Claims
     * @author 小易
     * @date 2022/12/6 10:24
     */
    public static Claims parseToken(String token) {
        return parseToken(null, token);
    }



    /** 测试代码 */
    public static void main(String[] args) {
        Map<String, Object> map = new HashMap<>();
        map.put("userId", 121);
        map.put("userName", "jacky");
        String token = createToken("123",map);
        System.out.println("token = " + token);
        Claims claims = parseToken("123",token);
        System.out.println("claims = " + claims);
        System.out.println("claims.getExpiration() = " + claims.getExpiration());
        System.out.println("claims.getId() = " + claims.getId());
    }

}
